import React, { useState, ReactNode } from 'react';
import { diffLines, Change } from 'diff';

interface VersionDiffProps {
  oldText: string;
  newText: string;
  contextLines?: number; // 默认上下文行数
}

interface DiffLine {
  type: 'context' | 'add' | 'remove';
  content: string;
  oldLineNumber: number | null;
  newLineNumber: number | null;
}

// 处理 diff 结果，生成带行号的结构
function buildDiffLines(oldText: string, newText: string): DiffLine[] {
  const diff: Change[] = diffLines(oldText, newText);
  let oldLine = 1;
  let newLine = 1;
  const lines: DiffLine[] = [];
  diff.forEach((part: Change) => {
    const partLines = part.value.split('\n');
    // 去除最后一个空行
    if (partLines[partLines.length - 1] === '') partLines.pop();
    partLines.forEach((line: string) => {
      if (part.added) {
        lines.push({
          type: 'add',
          content: line,
          oldLineNumber: null,
          newLineNumber: newLine++,
        });
      } else if (part.removed) {
        lines.push({
          type: 'remove',
          content: line,
          oldLineNumber: oldLine++,
          newLineNumber: null,
        });
      } else {
        lines.push({
          type: 'context',
          content: line,
          oldLineNumber: oldLine++,
          newLineNumber: newLine++,
        });
      }
    });
  });
  return lines;
}

// 生成折叠区块信息
function getBlocks(diffLines: DiffLine[], contextLines: number) {
  const blocks: { type: 'shown' | 'folded'; start: number; end: number }[] = [];
  let i = 0;
  while (i < diffLines.length) {
    if (diffLines[i].type !== 'context') {
      // 变动区块，前后各 contextLines 行
      const start = Math.max(0, i - contextLines);
      let end = i + 1;
      while (end < diffLines.length && diffLines[end].type !== 'context') end++;
      end = Math.min(diffLines.length, end + contextLines);
      // 合并与前一区块重叠
      if (blocks.length && blocks[blocks.length - 1].end >= start) {
        blocks[blocks.length - 1].end = end;
      } else {
        blocks.push({ type: 'shown', start, end });
      }
      i = end;
    } else {
      i++;
    }
  }
  // 其余为折叠区
  let lastEnd = 0;
  const allBlocks: { type: 'shown' | 'folded'; start: number; end: number }[] = [];
  blocks.forEach((b) => {
    if (b.start > lastEnd) {
      allBlocks.push({ type: 'folded', start: lastEnd, end: b.start });
    }
    allBlocks.push(b);
    lastEnd = b.end;
  });
  if (lastEnd < diffLines.length) {
    allBlocks.push({ type: 'folded', start: lastEnd, end: diffLines.length });
  }
  return allBlocks;
}

const FOLD_STEP = 20; // 每次展开20行

const VersionDiff: React.FC<VersionDiffProps> = ({ oldText, newText, contextLines = 3 }) => {
  const diffLines = buildDiffLines(oldText, newText);
  const initialBlocks = getBlocks(diffLines, contextLines);
  const [expandedBlocks, setExpandedBlocks] = useState<{ [key: number]: number }>({}); // 折叠区展开到哪一行
  const [expandAll, setExpandAll] = useState(false);

  // 展开全部
  const handleExpandAll = () => {
    setExpandAll(true);
  };

  // 展开某个折叠区
  const handleExpand = (blockIdx: number, direction: 'up' | 'down') => {
    setExpandedBlocks((prev) => {
      const cur = prev[blockIdx] || 0;
      return { ...prev, [blockIdx]: cur + FOLD_STEP };
    });
  };

  // 渲染区块
  const renderBlock = (block: { type: 'shown' | 'folded'; start: number; end: number }, idx: number) => {
    if (block.type === 'shown' || expandAll) {
      return diffLines.slice(block.start, block.end).map((line, i) => (
        <DiffRow key={`${block.start}-${i}-${line.oldLineNumber ?? ''}-${line.newLineNumber ?? ''}`} line={line} />
      ));
    } else {
      const total = block.end - block.start;
      const expanded = expandedBlocks[idx] || 0;
      const showCount = Math.min(total, expanded + contextLines * 2);
      const startIdx = block.start;
      const endIdx = block.start + showCount;
      const canExpandUp = startIdx > 0 && showCount < total;
      const canExpandDown = endIdx < block.end;
      return (
        <React.Fragment>
          {canExpandUp && (
            <FoldButton onClick={() => handleExpand(idx, 'up')}>↑ 向上展开 {FOLD_STEP} 行</FoldButton>
          )}
          {diffLines.slice(startIdx, endIdx).map((line, i) => (
            <DiffRow key={`${startIdx}-${i}-${line.oldLineNumber ?? ''}-${line.newLineNumber ?? ''}`} line={line} />
          ))}
          {canExpandDown && (
            <FoldButton onClick={() => handleExpand(idx, 'down')}>↓ 向下展开 {FOLD_STEP} 行</FoldButton>
          )}
          {!canExpandUp && !canExpandDown && (
            <div className="text-center text-xs text-gray-400 py-1">已全部展开</div>
          )}
        </React.Fragment>
      );
    }
  };

  return (
    <div className="border rounded bg-white overflow-x-auto text-sm font-mono">
      <div className="flex justify-between items-center px-2 py-1 border-b bg-gray-50">
        <span>版本差异</span>
        <button
          className="text-xs px-2 py-1 border rounded hover:bg-gray-100"
          onClick={handleExpandAll}
        >
          全部展开
        </button>
      </div>
      <div>
        <div className="grid grid-cols-[50px_50px_1fr] bg-gray-100 text-gray-500">
          <div className="px-2">旧行</div>
          <div className="px-2">新行</div>
          <div className="px-2">内容</div>
        </div>
        {initialBlocks.map((block, idx) => (
          <React.Fragment key={idx}>{renderBlock(block, idx)}</React.Fragment>
        ))}
      </div>
    </div>
  );
};

// 单行渲染
const DiffRow: React.FC<{ line: DiffLine }> = ({ line }) => {
  let bg = '';
  if (line.type === 'add') bg = 'bg-green-50';
  if (line.type === 'remove') bg = 'bg-red-50';
  return (
    <div className={`grid grid-cols-[50px_50px_1fr] border-b last:border-0 ${bg}`}>
      <div className="px-2 text-right text-gray-400 select-none">
        {line.oldLineNumber ?? ''}
      </div>
      <div className="px-2 text-right text-gray-400 select-none">
        {line.newLineNumber ?? ''}
      </div>
      <div className="px-2 whitespace-pre-wrap break-all">
        {line.content === '' ? <span className="text-gray-300">·</span> : line.content}
      </div>
    </div>
  );
};

// 折叠按钮
const FoldButton: React.FC<{ onClick: () => void; children: ReactNode }> = ({ onClick, children }) => (
  <div className="text-center py-1">
    <button
      className="text-xs px-2 py-1 border rounded bg-gray-50 hover:bg-gray-100 text-gray-500"
      onClick={onClick}
      type="button"
    >
      {children}
    </button>
  </div>
);

export default VersionDiff; 